import de.wwag.vdz.basis.configmanager.model.*
import de.wwag.vdz.basis.configmanager.model.rtt.*
import de.wwag.vdz.basis.kern.values.*
import de.wwag.vdz.basis.configmanager.model.Deployment
import de.wwag.vdz.basis.configmanager.model.Deployment.DeploymentType
import de.wwag.vdz.basis.configmanager.model.rtt.Regeltest.*
import static de.wwag.vdz.basis.configmanager.model.Deployment.DeploymentType.*
import static de.wwag.vdz.basis.configmanager.model.Regelwerk.Datenanreicherungsart.*;
import static de.wwag.vdz.basis.configmanager.model.rtt.Regeltest.Regelart.*
import de.wwag.vdz.basis.configmanager.model.rtt.Regeltest.Regelart
persist = []

currentRegelwerk = null
def regelwerk(name, selektor, art) {
	currentRegelwerk = new Regelwerk(bezeichnung: name, selektor: selektor, intranetGruppe: 'MxV_OE_IT_gesamt_auto', datenanreicherungsArt: art)
	persist << currentRegelwerk
}

abstract class AbstractBuilder extends BuilderSupport {
	def currentRegelwerk
	protected void setParent(Object parent, Object child) {}
	protected Object createNode(Object name) { createNode(name, [:], null) }
	protected Object createNode(Object name, Object value) { createNode(name, [:], value) }
	protected Object createNode(Object name, Map attributes) { createNode(name, attributes, null) }
	protected void nodeCompleted(Object parent, Object node) {}
}

class AktenBuilder extends AbstractBuilder {
    def sicht = false
    
    protected Object createNode(Object name){}
    protected Object createNode(Object name, Object value){
        if (!sicht) {
            sicht = true
            return new Aktensicht(regelwerk: currentRegelwerk, bezeichnung: name, rollen: value, knoten: [])
        } else {
            return new Aktenknoten(bezeichnung: name, gruppierbar: false, children: [], dokumenttypen: value)
        }
    }
    protected Object createNode(Object name, Map attributes){}
    protected Object createNode(Object name, Map attributes, Object value){
        new Aktenknoten(bezeichnung: name, gruppierbar: attributes['gruppierbar'], children: [], dokumenttypen: value)
    }
    protected void nodeCompleted(Object parent, Object node) {
        if (parent != null) {
            if (parent instanceof Aktensicht) {
                parent.knoten << node
                node.sicht = parent
            } else {
                parent.children << node
                node.parent = parent
            }
        }
    }
}

def Akte() {
	new AktenBuilder(currentRegelwerk: currentRegelwerk)
}

class OEBuilder extends AbstractBuilder {
	static fachIdCounter = 0
	protected Object createNode(Object name, Map attributes, Object value) {
		switch (name) {
		case 'OE':
			def b = value.split('/')
			return new Organisationseinheit(regelwerk: currentRegelwerk, kurzbezeichnungFirma: b[0], kurzbezeichnungOE: b[1], verantwortliche: attributes['verantwortliche'])
		case 'PPK':
			def user = []
			attributes['nichtKAP'].each { user << new Postkorbbenutzer(typ: Postkorbbenutzertyp.zugeordneterNichtKapBenutzer, benutzerId: it) }
			attributes['einsehAutomatisch'].each { user << new Postkorbbenutzer(typ: Postkorbbenutzertyp.Automatisch, benutzerId: it) }
			attributes['einsehManuell'].each { user << new Postkorbbenutzer(typ: Postkorbbenutzertyp.Manuell, benutzerId: it) }
		 	return new Postkorb(typ: Postkorbtyp.PPK, bezeichnung: value, owner: value, zugeordnetePostkorbbenutzer: user, gesperrt: attributes['gesperrt'] ?: false, fachId: fachIdCounter++)
		case 'SPK':
			attributes['fachId'] = fachIdCounter ++;
			return new Postkorb(typ: Postkorbtyp.SPK, bezeichnung: value, pushBerechtigt: attributes['push'], einsehBerechtigt: attributes['einseh'], fachId: fachIdCounter++)
		}
	}
	protected void nodeCompleted(Object parent, Object node) {
		if (parent != null && node != null) {
        	if (node instanceof Organisationseinheit) {
                parent.organisationseinheiten << node
				node.parent = parent
        	} else {
        		parent.postkoerbe << node
	            node.organisationseinheit = parent    	
        	}
		}
	}
}

def OE() {
	new OEBuilder(currentRegelwerk: currentRegelwerk)
}

class VorgangstypBuilder extends AbstractBuilder {
	static fachIdCounter = 0
	protected void setParent(Object parent, Object child){
		if (parent instanceof Vorgangstyp) {
			child.vorgangstyp = parent
			parent.aktivitaetstypDefinitionen << child
            parent.auswahlMoeglich = AuswahlMoeglichkeit.DialogDurchSBUndRegelwerk
		} else if (parent instanceof AktivitaetstypDefinition) {
			if (child instanceof AktivitaetstypDefinition) {
				child.vorgaenger = parent
				child.vorgangstyp = parent.vorgangstyp
				child.vorgangstyp.aktivitaetstypDefinitionen << child
			} else if (child instanceof BearbeitungsvermerkDefinition) {
				parent.bearbeitungsvermerk << child
				child.typ = parent
			}
		}
	}
	protected Object createNode(Object name, Map attributes, Object value){
		switch (name) {
		case 'Vorgangstyp':
			attributes['fachId'] = fachIdCounter ++;
			def vt = new Vorgangstyp(attributes)
			vt.gruppe = value
			vt.regelwerk = currentRegelwerk
			vt.aktivitaetstypDefinitionen = []
			value.vorgangstypen << vt
			return vt
		case 'MussAktivitaet':
			def atd = new AktivitaetstypDefinition(attributes)
			atd.bearbeitungsvermerk = []
			atd.typ = value
			atd.erforderlich = true
			atd.auswahlMoeglich = AuswahlMoeglichkeit.DialogDurchSBUndRegelwerk
			return atd
		case 'KannAktivitaet':
			def atd = new AktivitaetstypDefinition(attributes)
			atd.bearbeitungsvermerk = []
			atd.typ = value
			atd.erforderlich = false
			atd.auswahlMoeglich = AuswahlMoeglichkeit.DialogDurchSBUndRegelwerk
			return atd
		case 'Vermerk':
			def v = new BearbeitungsvermerkDefinition(attributes)
			v.vermerk = value
			return v
		}
	}
}

def newVT() {
	new VorgangstypBuilder(currentRegelwerk: currentRegelwerk)
}

def Rolle(attributes) {
	attributes['regelwerk'] = currentRegelwerk
	new Rolle(attributes)
}

def Prozessinfo(attributes) {
	attributes['regelwerk'] = currentRegelwerk
	new Prozessinfo(attributes)
}

def Vorgangstypgruppe(attributes) {
    attributes['regelwerk'] = currentRegelwerk
    new Vorgangstypgruppe(attributes)
}

def Dokumenttyp(attributes) {
    attributes['regelwerk'] = currentRegelwerk
    attributes['art'] = attributes['art'] ?: Dokumenttypart.EingangsDokumentSachbearbeiter
    attributes['auswahlMoeglich'] = attributes['auswahlMoeglich'] ?: randomAuswahlmoeglichkeit()
    new Dokumenttyp(attributes)
}

fachIdCounter = 0

def Aktivitaetstyp(attributes) {
    attributes['regelwerk'] = currentRegelwerk
    attributes['auswahlMoeglich'] = attributes['auswahlMoeglich'] ?: randomAuswahlmoeglichkeit()
    attributes['bearbeitungsUeberblickUeberspringen'] = attributes['bearbeitungsUeberblickUeberspringen'] ?: false
    attributes['direktrouting'] = attributes['direktrouting'] ?: false
    attributes['fertigstellungsvermerkErforderlich'] = attributes['fertigstellungsvermerkErforderlich'] ?: false
    attributes['maximaleTerminierungsdauer'] = attributes['maximaleTerminierungsdauer'] ?: 5
    attributes['prioBasis'] = attributes['prioBasis'] ?: 10
    attributes['prioSummand'] = attributes['prioSummand'] ?: 10
    attributes['fachId'] = fachIdCounter ++
    new Aktivitaetstyp(attributes)
}

def Bearbeitungsvermerk(attributes) {
    attributes['regelwerk'] = currentRegelwerk
    new Bearbeitungsvermerk(attributes)
}

def Einsprungpunkt(attributes) {
    attributes['regelwerk'] = currentRegelwerk
    new Einsprungpunkt(attributes)
}

def ReferenzMapping(attributes) {
    attributes['regelwerk'] = currentRegelwerk
    new ReferenzMapping(attributes)
}

def newUploaderSicht(kuerzel,prozessinfo,dokumenttypen,prozessinfos,freitextDokumenttyp,freitextProzessinfo){
	us = new UploaderSicht(kuerzel:kuerzel, bezeichnung:kuerzel, prozessinfo:prozessinfo,freitextDokumenttyp:freitextDokumenttyp,freitextProzessinfo:freitextProzessinfo)
	
	us.regelwerk = currentRegelwerk

	pis = []
	dts = []
	
	dokumenttypen.each { dts << new DokumenttypZuordnung(dokumenttyp:it, sicht:us) }
	prozessinfos.each { pis << new ProzessinfoZuordnung(prozessinfo:it, sicht:us) }
	
	us.dokumenttypen = dts
	us.prozessinfos = pis	

	return us 
}

def randomLong(maximum) {
    long rnd = (Math.round(Math.random() * maximum))
    return rnd
}

def randomString(prefix) {
    long rndSurfix = (Math.round(Math.random() * 1000))
    return "${prefix}${rndSurfix}"
}

def randomDoktypart() {
    asList = Arrays.asList(Dokumenttyp.Dokumenttypart.values());
    Collections.shuffle(asList);
    asList.get(0);
}

def randomAuswahlmoeglichkeit() {
    asList = Arrays.asList(AuswahlMoeglichkeit.values());
    Collections.shuffle(asList);
    asList.get(0);
}

def randomInt(int maximum) {
    Math.round(Math.random() * maximum)
}

def newVorgang(Ordnungsbegriff fuehrenderOb, String bezeichnung, Vorgangstyp typ){
	VorgangsDefinition v = new VorgangsDefinition()
	v.setBezeichnung(bezeichnung)
	v.setTyp(typ)
	v.setRegelwerk(currentRegelwerk)
	
	v.setAnzahlFolgeeingang(4)
    v.setStatus(Vorgangsstatus.ANGELEGT)
    v.setErstellungsdatum(new Date());
    
    v.setFuehrenderOrdnungsbegriff(fuehrenderOb)
    
	return v;
}

def newAktivitaet(String bezeichnung){
	AktivitaetsDefinition aktivitaet = new AktivitaetsDefinition()
    aktivitaet.setRegelwerk(currentRegelwerk)

    aktivitaet.setAnlagezeitpunkt(new Date());
    aktivitaet.setBezeichnung(bezeichnung);
    aktivitaet.setPrioritaet(9999)
    aktivitaet.setStatus(Aktivitaetsstatus.ANGELEGT)
    
    return aktivitaet;
}

def newDokument(String bezeichnung, Dokumenttyp dt){
	DokumentDefinition dok = new DokumentDefinition()
    dok.setRegelwerk(currentRegelwerk)

    dok.setBezeichnung(bezeichnung);
	dok.setEaKennzeichen(EAKennzeichen.Eingang);
	dok.setImagetype(Imagetype.PDF)
	dok.setKommunikationskanal(Kommunikationskanal.EMail)
	dok.setIndiziergrad(Indiziergrad.DokumentTypManuellTeilindiziert);
	dok.setIndizierplatz(IndizierPlatz.Einzelarbeitsplatz);
	dok.setEingangsadresse("utww.de")
	
	dok.getDokumenttypen().add(dt)

    return dok;
}

def newSuite(String bezeichnung){
    RegeltestSuite rts = new RegeltestSuite()
    rts.setRegelwerk(currentRegelwerk)
    
    rts.setBezeichnung(bezeichnung)
    
    return rts
}

def newTest(RegeltestSuite suite, String bezeichnung, Regelart art){
    Regeltest rt = null
    switch(art) {
       case Vorgangsbestimmung: rt = new VorgangsbestimmungTest(); break;
       case Routing: rt = new RoutingTest(); break;
       case Doktypverfeinerung: rt = new DokumenttypVerfeinerungTest(); break;
    }
   
    rt.setRegelwerk(currentRegelwerk)
    
    if(suite != null){
       rt.setSuite(suite)
       suite.getRegeltests().add(rt)
    }
    
    rt.setBezeichnung(bezeichnung);
    
    return rt
}

def newDeployment(DeploymentType type){
	Deployment d = new Deployment()
	d.setRegelwerk(currentRegelwerk)
	
	d.setType(type)
	d.setConfigTest(type == Test ? dummyDeployConfig() : null)
	d.setConfigProd(type == Prod ? dummyDeployConfig() : null)
	
	return d
}

def dummyDeployConfig(){
    DeploymentConfig d = new DeploymentConfig()
    d.setContent("empty")
    
    return d
}

def newOrdnungsbegriff(String obTyp, String obWert){
    Ordnungsbegriff o = new Ordnungsbegriff()
    o.setTyp(obTyp)
    o.setWert(obWert)
    
    return o
}

def newDatenanreicherung(String bezeichnung, Ordnungsbegriff ob){
	klda = new KrankenLeistungDatenanreicherung();
	klda.regelwerk = currentRegelwerk
	klda.routingKennzeichen='routingKZ'
	klda.agenturnummer='agentur'
	klda.vertriebsweg='vertriebsweg'
	klda.gesellschaft='gesellschaft'
	klda.nameVN='Hans Wurst'
	klda.produktSchluessel='4711'
	klda.werkstattbindung=true
	klda.ordnungsbegriff = ob
	klda.bezeichnung = bezeichnung
	return klda
}
